﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet;
using Docker.DotNet.Models;

namespace DockerPlay
{
    public class DockerHelper
    {
        private readonly DockerClient client;
        private List<ContainerStatus> dockerContainersStatus;
        public DockerHelper(string dockerConnectioString)
        {
            client = new DockerClientConfiguration(new Uri(dockerConnectioString)).CreateClient();
            GetContainersIdAndStatus().Wait();
        }
        public async Task<List<ContainerStatus>> GetContainersIdAndStatus()
        {
            var containers = await client.Containers.ListContainersAsync(new ContainersListParameters() { Limit = 10 });

            dockerContainersStatus = new List<ContainerStatus>();
            foreach (var cont in containers)
            {
                dockerContainersStatus.Add(
                      new ContainerStatus()
                      {
                          ContainerId = cont.ID,
                          Name = cont.Names[0].Remove(0, 1).Trim().ToEnum<ContainerName>(), //ContainerName.ga_backup_from_b,
                          State = cont.State.ToEnum<DockerContainerState>(),
                          Id = Guid.NewGuid(),
                          Date = DateTime.UtcNow,
                      });

            }
            //todo: say what image is missing
            if (dockerContainersStatus.Count != Enum.GetNames(typeof(ContainerName)).Length)
            {
                throw new Exception("Missing docker image ");
            }
            return dockerContainersStatus;
        }

        public async Task StartContainer(ContainerName name)
        {
            await client.Containers.StartContainerAsync(dockerContainersStatus.First(x => x.Name == name).ContainerId,
                    new ContainerStartParameters());
            while (await GetContainerStatus(name) != DockerContainerState.running)
            {
                //TODO: Find another way
                Thread.Sleep(5);
            }
        }

        public async Task StopContainer(ContainerName name)
        {
            await client.Containers.StopContainerAsync(dockerContainersStatus.First(x => x.Name == name).ContainerId,
                    new ContainerStopParameters(), CancellationToken.None);
            while (await GetContainerStatus(name) != DockerContainerState.exited)
            {
                //TODO: Find another way
                Thread.Sleep(5);
            }
        }

        public async Task<DockerContainerState> GetContainerStatus(ContainerName name)
        {

            //var containers = await client.Containers.ListContainersAsync(new ContainersListParameters());
            var inspect = await client.Containers.InspectContainerAsync(dockerContainersStatus.First(x => x.Name == name).ContainerId);
            return (DockerContainerState)Enum.Parse(typeof(DockerContainerState), inspect.State.Status);
        }

        public async Task<ContainerName> GetActiveContainer()
        {
            if (await GetContainerStatus(ContainerName.ga_mongo_a_27017) == DockerContainerState.running)
                return ContainerName.ga_mongo_a_27017;

            if (await GetContainerStatus(ContainerName.ga_mongo_b_27017) == DockerContainerState.running)
                return ContainerName.ga_mongo_b_27017;

            throw new Exception("There is no active container for GA mongoDB. You need to start active container manually ");
        }

        public async Task<ContainerProcessesResponse> GetContainerProcess(ContainerName name)
        {

            var process =
                await
                    client.Containers.ListProcessesAsync(dockerContainersStatus.First(x => x.Name == name).ContainerId,
                        new ContainerListProcessesParameters());
            return process;
        }
    }
}
